package com.tanhua.server.service;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.aliyun.oss.OSSClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.server.config.AliyunConfig;
import com.tanhua.server.mapper.VoiceMapper;
import com.tanhua.server.pojo.User;
import com.tanhua.server.pojo.UserInfo;
import com.tanhua.server.pojo.Voice;
import com.tanhua.server.utils.LocalDateTimeInterval;
import com.tanhua.server.utils.UserThreadLocal;
import com.tanhua.server.vo.UserVoice;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class VoiceService {
    private final VoiceMapper voiceMapper;
    private final RedisTemplate<String, String> redisTemplate;
    private final UserInfoService userInfoService;
    protected final FastFileStorageClient storageClient;
    private final FdfsWebServer fdfsWebServer;
    private final AliyunConfig aliyunConfig;

    public VoiceService(VoiceMapper voiceMapper, RedisTemplate<String, String> redisTemplate, UserInfoService userInfoService, FastFileStorageClient storageClient, FdfsWebServer fdfsWebServer, AliyunConfig aliyunConfig) {
        this.voiceMapper = voiceMapper;
        this.redisTemplate = redisTemplate;
        this.userInfoService = userInfoService;
        this.storageClient = storageClient;
        this.fdfsWebServer = fdfsWebServer;
        this.aliyunConfig = aliyunConfig;
    }

    /**
     * 接收语音
     *
     * @return 前端需要的参数对象
     */
    public UserVoice getVoice() {
        User user = UserThreadLocal.get();
        UserVoice userVoice = new UserVoice();

        String redisKey = "GET_VOICE_TIMES" + user.getId();
        if (Boolean.FALSE.equals(this.redisTemplate.hasKey(redisKey))) {
            // redis中没有该key, 说明key过期了, 从新赋值, 设置过期时间为到当前12点
            Long interval = LocalDateTimeInterval.geInterval(LocalDateTime.now());
            this.redisTemplate.opsForValue().set(redisKey, "3", interval, TimeUnit.MILLISECONDS);
        }

        // 判断用户是否有接收语音的次数
        String remainingTimes = this.redisTemplate.opsForValue().get(redisKey);
        if ("0".equals(remainingTimes)) {
            userVoice.setRemainingTimes(0);
            return userVoice;
        }

        // 从数据库获取除了自己语音信息之外的信息
        QueryWrapper<Voice> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("user_id", user.getId());
        List<Voice> voiceList = this.voiceMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(voiceList)) {
            return userVoice;
        }

        // 循环变量
        int i = 0;
        Voice voice = null;
        while (i < voiceList.size()) {
            // 定义一个随机索引
            int temp = RandomUtils.nextInt(0, voiceList.size());
            voice = voiceList.get(temp);
            UserInfo userInfo = this.userInfoService.queryUserInfoByUserId(voice.getUserId());
            if (userInfo != null) {
                // 自己的男女
                UserInfo myUserInfo = this.userInfoService.queryUserInfoByUserId(user.getId());
                Integer mySexValue = myUserInfo.getSex().getValue();
                // 判断是否收到的是异性的语音
                if (!userInfo.getSex().getValue().equals(mySexValue)) {
                    // 如果是, 就封装数据
                    userVoice.setId(voice.getUserId());
                    userVoice.setAge(userInfo.getAge());
                    userVoice.setAvatar(userInfo.getLogo());
                    userVoice.setGender(userInfo.getSex().getValue() == 1 ? "man" : "woman");
                    userVoice.setNickname(userInfo.getNickName());
                    userVoice.setSoudUrl(voice.getSoundUrl());
                    Voice judgeVoice = this.voiceMapper.selectById(user.getId());

                    // 设置自己的还剩下的语音次数
                    String s = this.redisTemplate.opsForValue().get(redisKey);
                    if (s != null) {
                        String time = String.valueOf(Integer.parseInt(s) - 1);
                        Long interval = LocalDateTimeInterval.geInterval(LocalDateTime.now());
                        redisTemplate.opsForValue().set(redisKey, time, interval, TimeUnit.MILLISECONDS);
                        userVoice.setRemainingTimes(Integer.parseInt(s) - 1);
                    }

                    break;
                }
            }
        }
        // 删除数据库中的语音信息
        if (voice != null) {
            this.voiceMapper.deleteById(voice.getId());
        }

        return userVoice;

    }

    /**
     * 发送语音
     *
     * @param file 语音文件
     * @return 是否发送成功
     */
    public boolean sendVoice(MultipartFile file) {
        User user = UserThreadLocal.get();
        Voice voice = new Voice();
        voice.setUserId(user.getId());

        // 文件新路径
        String fileName = file.getOriginalFilename();
        String filePath = getFilePath(fileName);

        OSSClient ossClient = aliyunConfig.oSSClient();
        try {
            // 上传到阿里云
            // 目录结构：voice/2018/12/29/xxxx.mp3
            ossClient.putObject(aliyunConfig.getBucketName(), filePath, new ByteArrayInputStream(file.getBytes()));

            // 保存到本地
            StorePath storePath = storageClient.uploadFile(file.getInputStream(),
                    file.getSize(),
                    StringUtils.substringAfter(file.getOriginalFilename(), "."),
                    null);

            voice.setSoundUrl(fdfsWebServer.getWebServerUrl() + "/" + storePath.getFullPath());

            return this.voiceMapper.insert(voice) > 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private String getFilePath(String sourceFileName) {
        DateTime dateTime = new DateTime();
        return "voice/" + dateTime.toString("yyyy")
                + "/" + dateTime.toString("MM") + "/"
                + dateTime.toString("dd") + "/" + System.currentTimeMillis() +
                RandomUtils.nextInt(100, 9999) + "." +
                StringUtils.substringAfterLast(sourceFileName, ".");
    }
}
